home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 4
/
Apprentice-Release4.iso
/
Languages
/
PowerMacOberon 1.2
/
Source
/
Tools
/
Xref.Mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1995-08-22
|
8KB
|
280 lines
Syntax10.Scn.Fnt
FoldElems
Syntax10.Scn.Fnt
(*----------------------------------------------------------------
Xref creates a cross reference list for Oberon-2 programs.
Xref.List (^ | * | {filename} ~)
opens a viewer showing the source text of the specified file(s) with linenumbers
as well as a sorted list of names and the line numbers where they occur in the
source text.
Xref.SetLineLength number
allows the user to specify the desired line length in characters. Default is 120.
Xref.SetNumberLength number
allows the user to specify the desired number of digits per line number in order
to be able to print the line numbers in an aligned way. Default is 5.
----------------------------------------------------------------*)
Syntax10i.Scn.Fnt
StampElems
Alloc
8 May 95
Syntax10b.Scn.Fnt
Documentation
MODULE Xref; (*HM 9 Feb 89 /
IMPORT Viewers, MenuViewers, TextFrames, Texts, Oberon, Strings;
CONST
hTabSize = 569; (*hash table size: 4*i+3*)
kTabSize = 45; (*at most 45 keywords*)
kln = 15; (*max.length of a keyword*)
Alfa = ARRAY kln OF CHAR;
Ref = POINTER TO Item;
Item = RECORD
lno: INTEGER;
next: Ref
END;
Word = RECORD
key: Alfa;
first: Ref
END;
HashTab = ARRAY hTabSize OF Word; (*hash table*)
w: Texts.Writer;
nk: INTEGER; (*nr.of keywords*)
n: INTEGER; (*current line number*)
nopl: INTEGER; (*nr.of line numbers per page*)
llng: INTEGER; (*line length*)
dgpn: INTEGER; (*digits per number*)
key: ARRAY kTabSize OF Alfa; (*keyword list*)
PROCEDURE InitTab; (*initialize keyword table*)
PROCEDURE AddKey(s: ARRAY OF CHAR);
BEGIN
INC(nk); COPY(s, key[nk])
END AddKey;
BEGIN
nk:=0;
AddKey("ARRAY");
AddKey("BEGIN");
AddKey("BOOLEAN");
AddKey("CASE");
AddKey("CHAR");
AddKey("CLOSE");
AddKey("CONST");
AddKey("DEFINITION");
AddKey("DIV");
AddKey("DO");
AddKey("ELSE");
AddKey("ELSIF");
AddKey("END");
AddKey("EXIT");
AddKey("FALSE");
AddKey("IF");
AddKey("IMPORT");
AddKey("IN");
AddKey("INTEGER");
AddKey("IS");
AddKey("LONGINT");
AddKey("LONGREAL");
AddKey("LOOP");
AddKey("MOD");
AddKey("MODULE");
AddKey("NIL");
AddKey("OF");
AddKey("OR");
AddKey("POINTER");
AddKey("PROCEDURE");
AddKey("REAL");
AddKey("RECORD");
AddKey("REPEAT");
AddKey("RETURN");
AddKey("SET");
AddKey("SHORTINT");
AddKey("THEN");
AddKey("TO");
AddKey("TRUE");
AddKey("TYPE");
AddKey("UNTIL");
AddKey("VAR");
AddKey("WHILE");
AddKey("WITH")
END InitTab;
PROCEDURE OpenViewer(VAR lst: Texts.Text);
VAR menu: Texts.Text; v: Viewers.Viewer; x, y: INTEGER;
BEGIN
Oberon.AllocateUserViewer(0, x, y);
v := MenuViewers.New(
TextFrames.NewMenu("Xref.LST", "System.Close System.Copy System.Grow Edit.Store"),
TextFrames.NewText(TextFrames.Text(""), 0), TextFrames.menuH, x, y);
lst := v.dsc.next(TextFrames.Frame).text
END OpenViewer;
PROCEDURE WriteLnr;
BEGIN
INC(n); Texts.WriteInt(w, n, 4); Texts.WriteString(w, " ")
END WriteLnr;
PROCEDURE NoKey(id: ARRAY OF CHAR): BOOLEAN;
VAR i, j, k: INTEGER;
BEGIN
i:=0; j:=nk - 1;
REPEAT
k:=(i+j) DIV 2;
IF id < key[k] THEN j:=k - 1 ELSE i:=k + 1 END
UNTIL i > j;
IF j < 0 THEN RETURN TRUE ELSE RETURN key[j] # id END
END NoKey;
PROCEDURE Search(id: ARRAY OF CHAR; VAR t: HashTab);
VAR h, d, len: INTEGER; x: Ref;
BEGIN
len:=Strings.Length(id);
h:=(ORD(id[0]) + 17*ORD(id[len-1]) + len) * 7 MOD hTabSize;
d:= - hTabSize;
NEW(x); x.lno:=n;
LOOP
IF t[h].key[0] = 0X THEN (*new entry*)
COPY(id, t[h].key); t[h].first:=x; x.next:=NIL; EXIT
ELSIF t[h].key = id THEN (*found*)
x.next:=t[h].first; t[h].first:=x; EXIT
ELSE
INC(d, 2); IF d = hTabSize THEN HALT(20) END;
INC(h, ABS(d)); IF h >= hTabSize THEN DEC(h, hTabSize) END
END
END Search;
PROCEDURE Sort(VAR t: HashTab; l, r: INTEGER);
VAR i, j: INTEGER; x: Alfa; w: Word;
BEGIN
i:=l; j:=r; x:=t[(i+j) DIV 2].key;
REPEAT
WHILE t[i].key < x DO INC(i) END;
WHILE x < t[j].key DO DEC(j) END;
IF i <= j THEN
w:=t[i]; t[i]:=t[j]; t[j]:=w;
INC(i); DEC(j)
END
UNTIL i > j;
IF l < j THEN Sort(t, l, j) END;
IF i < r THEN Sort(t, i, r) END
END Sort;
PROCEDURE PrintWord(word: Word);
VAR i, l, wl: INTEGER; x, y, z: Ref;
BEGIN
wl:=Strings.Length(word.key);
Texts.WriteString(w, " "); Texts.WriteString(w, word.key);
i:=wl; WHILE i < kln DO Texts.Write(w, " "); INC(i) END; (*fill with blanks*)
x:=word.first; y:=x.next; x.next:=NIL;
WHILE y # NIL DO (*invert order of line numbers*)
z:=y.next; y.next:=x; x:=y; y:=z
END;
l:=0;
REPEAT
IF l = nopl THEN
Texts.WriteLn(w); l:=0; i:=0; WHILE i < kln + 2 DO Texts.Write(w, " "); INC(i) END
END;
INC(l); Texts.WriteInt(w, x.lno, dgpn); x:=x.next
UNTIL x = NIL;
Texts.WriteLn(w)
END PrintWord;
PROCEDURE PrintTable(VAR t: HashTab);
VAR i, m: INTEGER;
BEGIN (*compress table*)
m:=0; i:=0;
WHILE i < hTabSize DO
IF t[i].key[0] # 0X THEN t[m]:=t[i]; INC(m) END;
INC(i)
END;
IF m > 0 THEN Sort(t, 0, m-1) END;
nopl:=(llng-kln-2) DIV dgpn;
i:=0; WHILE i < m DO PrintWord(t[i]); INC(i) END
END PrintTable;
PROCEDURE Process (src: Texts.Text); (* marked viewer *)
VAR r: Texts.Reader; lst: Texts.Text; t: HashTab; id: Alfa; ch, och: CHAR; level, k: INTEGER;
PROCEDURE NextCh;
BEGIN
Texts.Write(w, ch); Texts.Read(r, ch)
END NextCh;
BEGIN
OpenViewer(lst);
n:=0; WriteLnr;
k:=0; WHILE k < hTabSize DO t[k].key[0]:=0X; t[k].first:=NIL; INC(k) END;
Texts.OpenReader(r, src, 0); Texts.Read(r, ch);
WHILE ch # 0X DO
CASE ch OF
"A".."Z", "a".."z":
k:=0;
REPEAT
IF k < kln THEN id[k]:=ch; INC(k) END;
NextCh
UNTIL ~ (((CAP(ch)>="A") & (CAP(ch)<="Z")) OR ((ch>="0") & (ch<="9")));
IF k >= kln THEN k:=kln - 1 END; id[k]:=0X;
IF NoKey(id) THEN Search(id, t) END
| "0".."9":
REPEAT NextCh UNTIL (ch >= "9") OR (ch <= "0")
| "'", 22X:
och:=ch;
LOOP
NextCh; IF (ch = 0X) OR (ch = 0DX) THEN EXIT END;
IF ch = och THEN NextCh; EXIT END
END
| 0DX:
NextCh; WriteLnr
| "(":
NextCh;
IF ch = "*" THEN
NextCh; level:=1;
LOOP
IF ch = 0X THEN EXIT
ELSIF ch = 0DX THEN NextCh; WriteLnr
ELSIF ch = "*" THEN
NextCh;
IF ch = ")" THEN
NextCh; DEC(level);
IF level = 0 THEN EXIT END
END
ELSIF ch = "(" THEN
NextCh;
IF ch = "*" THEN NextCh; INC(level) END
ELSE NextCh
END
END (*LOOP*)
END
ELSE
NextCh
END (*CASE*)
END;
Texts.WriteLn(w); Texts.WriteLn(w);
PrintTable(t);
Texts.Append(lst, w.buf)
END Process;
PROCEDURE List*;
VAR s: Texts.Scanner; src, t: Texts.Text; beg, end, time: LONGINT; v : Viewers.Viewer;
BEGIN
Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s);
IF (s.class = Texts.Char) & (s.c = "^") THEN
Oberon.GetSelection(t, beg, end, time);
IF time >= 0 THEN Texts.OpenScanner(s, t, beg); Texts.Scan(s) END
END;
IF (s.class = Texts.Char) & (s.c = "*") THEN
v := Oberon.MarkedViewer(); src := v.dsc.next(TextFrames.Frame).text;
Process(src)
ELSE
WHILE s.class = Texts.Name DO
NEW(src); Texts.Open(src, s.s);
Process(src);
Texts.Scan(s)
END
END List;
PROCEDURE IntPar(min, max: LONGINT): INTEGER;
VAR par: Oberon.ParList; s: Texts.Scanner; i: LONGINT;
BEGIN
par:=Oberon.Par; Texts.OpenScanner(s, par.text, par.pos); Texts.Scan(s);
IF s.class = 3 THEN i:=s.i ELSE i:=0 END;
IF i < min THEN i:=min ELSIF i > max THEN i:=max END;
RETURN SHORT(i)
END IntPar;
PROCEDURE SetLineLength*; (* number *)
BEGIN
llng:=IntPar(kln + dgpn + 1, 120)
END SetLineLength;
PROCEDURE SetNumberLength*; (* number *)
BEGIN
dgpn:=IntPar(0, 5)
END SetNumberLength;
BEGIN
Texts.OpenWriter(w); llng:=100; dgpn:=5; InitTab
END Xref.